
function CacheManager()
{


this.Initialize = _initialize;
this.GetElement = _getElement;
this.PutElement = _putElement;
this.ExecuteCommand = _executeRemoteCommand;
this.ClearCache = _clearCache;
this.Contains = _containsElement;
this.AbstractDataType = _getAbstractDataType;
this.GetDataType = _getDataType;
this.GetOpDataType = _getOpDataType;
this.GetField = _getField;
this.GetRelatedEntity = _getRelatedEntity;
this.QueryData	= _queryData;
this.GetQuery = _getQuery;
this.OnPopulateFieldList = null;




var _oaCache = new Array();

var _oXml	= CreateXmlDocument(false);

var _asLookupIcons = new Array();
this.LookupIcons = _asLookupIcons;

var _oQueryXml = CreateXmlDocument(false);




function _initialize(bConditionExpression)
{



_oaCache["Entity"] = new Array();


_oaCache["Field"] = new Array();


_oaCache["Query"] = new Array();


_oaCache["Operator"] = new Array();


var oaOpNames = _populateOpNames();


_oaCache["Operator"]["number"] = _createOpCtrl(oaOpNames, "eq;ne;gt;ge;lt;le;not-null;null");
if(bConditionExpression == null || bConditionExpression == "undefined")
{
_oaCache["Operator"]["string"] = _createOpCtrl(oaOpNames, "eq;ne;contains;doesnotcontain;beginswith;doesnotbeginwith;endswith;doesnotendwith;not-null;null");
_oaCache["Operator"]["memo"] = _createOpCtrl(oaOpNames, "contains;doesnotcontain;beginswith;doesnotbeginwith;endswith;doesnotendwith;not-null;null");
}
else
{
_oaCache["Operator"]["string"] = _createOpCtrl(oaOpNames, "eq;ne;contains;doesnotcontain;beginswith;doesnotbeginwith;endswith;doesnotendwith;not-null;null;in;notin;gt;ge;lt;le");
_oaCache["Operator"]["memo"] = _createOpCtrl(oaOpNames, "eq;ne;contains;doesnotcontain;beginswith;doesnotbeginwith;endswith;doesnotendwith;not-null;null;in;notin;gt;ge;lt;le");
}

_oaCache["Operator"]["date"] = _createOpCtrl(oaOpNames, "on;on-or-after;on-or-before;yesterday;today;tomorrow;next-seven-days;last-seven-days;next-week;last-week;this-week;next-month;last-month;this-month;next-year;last-year;this-year;last-x-hours;next-x-hours;last-x-days;next-x-days;last-x-weeks;next-x-weeks;last-x-months;next-x-months;last-x-years;next-x-years;anytime;olderthan-x-months;not-null;null");
_oaCache["Operator"]["picklist"] = _createOpCtrl(oaOpNames, "eq;ne;not-null;null");
_oaCache["Operator"]["picklistwithname"] = _createOpCtrl(oaOpNames, "eq;ne;not-null;null;contains;doesnotcontain;beginswith;doesnotbeginwith;endswith;doesnotendwith");
_oaCache["Operator"]["language"] = _createOpCtrl(oaOpNames, "eq;ne;not-null;null;eq-userlanguage");
_oaCache["Operator"]["lookup"] = _createOpCtrl(oaOpNames, "eq;ne;not-null;null");
_oaCache["Operator"]["lookupwithname"] = _createOpCtrl(oaOpNames, "eq;ne;not-null;null;contains;doesnotcontain;beginswith;doesnotbeginwith;endswith;doesnotendwith");
_oaCache["Operator"]["lookupwithuser"] = _oaCache["Operator"]["owner"] = _createOpCtrl(oaOpNames, "eq-userid;ne-userid;eq;ne;not-null;null");
_oaCache["Operator"]["lookupwithuserwithname"] = _oaCache["Operator"]["ownerwithname"] = _createOpCtrl(oaOpNames, "eq-userid;ne-userid;eq;ne;not-null;null;contains;doesnotcontain;beginswith;doesnotbeginwith;endswith;doesnotendwith");

_oaCache["ConditionControlOperator"] = new Array();
_oaCache["ConditionControlOperator"]["date"] = _createOpCtrl(oaOpNames, "eq;ne;gt;ge;lt;le;on;not-on;on-or-after;on-or-before;not-null;null");
_oaCache["ConditionControlOperator"]["lookupwithuser"] = _oaCache["ConditionControlOperator"]["owner"] = _createOpCtrl(oaOpNames, "eq;ne;not-null;null");
_oaCache["ConditionControlOperator"]["lookupwithuserwithname"] = _oaCache["ConditionControlOperator"]["ownerwithname"] = _createOpCtrl(oaOpNames, "eq;ne;not-null;null;contains;doesnotcontain;beginswith;doesnotbeginwith;endswith;doesnotendwith");
_oaCache["ConditionControlOperator"]["partylist"] = _createOpCtrl(oaOpNames, "eq;ne;not-null;null;contains;doesnotcontain");


_oaCache["ValueControl"] = new Array();


_oaCache["UserQuery"] = new Array();


_oaCache["SystemQuery"] = new Array();


_oaCache["DefaultAdvFindView"] = new Array();

}




function _populateOpNames()
{

var oaOpNames =  new Array();


oaOpNames["eq"] = LOCID_AF_EQUALS;
oaOpNames["ne"] = LOCID_AF_DOESNOTEQUAL;
oaOpNames["contains"] = LOCID_AF_CONTAINS;
oaOpNames["doesnotcontain"] = LOCID_AF_DOESNOTCONTAIN;
oaOpNames["beginswith"] = LOCID_AF_BEGINSWITH;
oaOpNames["doesnotbeginwith"] = LOCID_AF_DOESNOTBEGINWITH;
oaOpNames["endswith"] = LOCID_AF_ENDSWITH;
oaOpNames["doesnotendwith"] = LOCID_AF_DOESNOTENDWITH;
oaOpNames["not-null"] = LOCID_AF_CONTAINSDATA;
oaOpNames["null"] = LOCID_AF_DOESNOTCONTAINDATA;
oaOpNames["gt"] = LOCID_AF_ISGREATERTHAN;
oaOpNames["ge"] = LOCID_AF_ISGREATERTHANOREQUALTO;
oaOpNames["lt"] = LOCID_AF_ISLESSTHAN;
oaOpNames["le"] = LOCID_AF_ISLESSTHANOREQUALTO;
oaOpNames["in"] = LOCID_AF_IN;
oaOpNames["notin"] = LOCID_AF_NOTIN;
oaOpNames["on"] = LOCID_AF_ON;
oaOpNames["not-on"] = LOCID_AF_NOTON;
oaOpNames["after"] = LOCID_AF_AFTER;
oaOpNames["on-or-after"] = LOCID_AF_ONORAFTER;
oaOpNames["before"] = LOCID_AF_BEFORE;
oaOpNames["on-or-before"] = LOCID_AF_ONORBEFORE;
oaOpNames["yesterday"] = LOCID_AF_YESTERDAY;
oaOpNames["today"] = LOCID_AF_TODAY;
oaOpNames["tomorrow"] = LOCID_AF_TOMORROW;
oaOpNames["next-seven-days"] = LOCID_AF_INTHENEXT7DAYS;
oaOpNames["last-seven-days"] = LOCID_AF_INTHELAST7DAYS;
oaOpNames["next-week"] = LOCID_AF_NEXTWEEK;
oaOpNames["last-week"] = LOCID_AF_LASTWEEK;
oaOpNames["this-week"] = LOCID_AF_THISWEEK;
oaOpNames["next-month"] = LOCID_AF_NEXTMONTH;
oaOpNames["last-month"] = LOCID_AF_LASTMONTH;
oaOpNames["this-month"] = LOCID_AF_THISMONTH;
oaOpNames["next-year"] = LOCID_AF_NEXTYEAR;
oaOpNames["last-year"] = LOCID_AF_LASTYEAR;
oaOpNames["this-year"] = LOCID_AF_THISYEAR;
oaOpNames["anytime"] = LOCID_AF_ANYTIME;
oaOpNames["eq-userid"] = LOCID_AF_EQUALSCURRENTUSER;
oaOpNames["ne-userid"] = LOCID_AF_DOESNOTEQUALCURRENTUSER;
oaOpNames["last-x-hours"] = LOCID_AF_LASTXHOURS;
oaOpNames["next-x-hours"] = LOCID_AF_NEXTXHOURS;
oaOpNames["last-x-days"] = LOCID_AF_LASTXDAYS;
oaOpNames["next-x-days"] = LOCID_AF_NEXTXDAYS;
oaOpNames["last-x-weeks"] = LOCID_AF_LASTXWEEKS;
oaOpNames["next-x-weeks"] = LOCID_AF_NEXTXWEEKS;
oaOpNames["last-x-months"] = LOCID_AF_LASTXMONTHS;
oaOpNames["next-x-months"] = LOCID_AF_NEXTXMONTHS;
oaOpNames["last-x-years"] = LOCID_AF_LASTXYEARS;
oaOpNames["next-x-years"] = LOCID_AF_NEXTXYEARS;
oaOpNames["eq-userlanguage"] = LOCID_AF_EQUSERLANGUAGE;
oaOpNames["olderthan-x-months"] = LOCID_AF_OLDERTHANXMONTHS;

return oaOpNames;
}


function _createOpCtrl(aoOpNames, sOpList)
{
var aoOpList = sOpList.split(";");
var oSelCtrl = new Select();
var iLen = aoOpList.length;
var sExp = "";
for(var i=0; i<iLen; i++)
{

switch(aoOpList[i])
{
case "contains":
sExp = "fetchOp=\"like\" fetchVal=\"%{0}%\"";
break;
case "beginswith":
sExp = "fetchOp=\"like\" fetchVal=\"{0}%\"";
break;
case "endswith":
sExp = "fetchOp=\"like\" fetchVal=\"%{0}\"";
break;
case "doesnotcontain":
sExp = "fetchOp=\"not-like\" fetchVal=\"%{0}%\"";
break;
case "doesnotbeginwith":
sExp = "fetchOp=\"not-like\" fetchVal=\"{0}%\"";
break;
case "doesnotendwith":
sExp = "fetchOp=\"not-like\" fetchVal=\"%{0}\"";
break;
}
oSelCtrl.AddOption(aoOpNames[aoOpList[i]],aoOpList[i],sExp);
}


oSelCtrl.Render();
return oSelCtrl;
}

function _getRelatedEntity(sRelatedEntity, sFrom, sTo, sEntity)
{

var oNode = _oXml.selectSingleNode("/related");
if(IsNull(oNode) || oNode.attributes[0].text!=sEntity)
{

var sRelatedXml = "<related entity=\"" + CrmEncodeDecode.CrmXmlEncode(sEntity) + "\">" + _getElement("Entity", sEntity) + "</related>";
_oXml.loadXML(sRelatedXml);
}

return _oXml.selectSingleNode("/related/option[@entity=\"" + sRelatedEntity + "\" and @from=\"" + sFrom + "\" and @to=\"" + sTo + "\"]");
}



function _getField(sField, sEntity)
{

var oNode = _oXml.selectSingleNode("/fields");
if(IsNull(oNode) || oNode.attributes[0].text!=sEntity)
{

var sFieldsXml = "<fields entity=\"" + CrmEncodeDecode.CrmXmlEncode(sEntity) + "\">" + _getElement("Field", sEntity) + "</fields>";
_oXml.loadXML(sFieldsXml);
}

return _oXml.selectSingleNode("/fields/option[@value=\"" + sField + "\" or @nameattr=\"" + sField + "\"]");
}


function _getDataType(sField, sEntity)
{
var oNode = _getField(sField, sEntity);
if(!IsNull(oNode))
{
return _getAbstractDataType(oNode);
}
return "custom";
}

function _getOpDataType(oNode)
{
switch(oNode.getAttribute("datatype"))
{
case "language":
return "language";
break;

default:
return _getAbstractDataType(oNode);
}
}




function _getFieldList(sXml, sEntity)
{

var fnCallback = this.OnPopulateFieldList;
if(!IsNull(fnCallback) && "function"==typeof(fnCallback))
{

oArgs = new Object();
oArgs.sEntityName = sEntity;
oArgs.sCustomFields = "";
fnCallback(oArgs);
if(oArgs.sCustomFields.length > 0)
{
sXml = sXml.replace("</fields>", oArgs.sCustomFields + "</fields>");
}
}


var oXslDoc = CreateXmlDocument(false);

oXslDoc.loadXML("<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'><xsl:output method='xml' omit-xml-declaration='yes'/><xsl:template match='/fields'><xsl:apply-templates select='result'><xsl:sort select='.' lang='" + XML_LANGUAGE_NAME + "'/></xsl:apply-templates></xsl:template><xsl:template match='result'><option><xsl:apply-templates select='@*'/><xsl:value-of select='.'/></option></xsl:template><xsl:template match='@*'><xsl:attribute name='{name()}'><xsl:value-of select='.' /></xsl:attribute></xsl:template></xsl:stylesheet>");


var oXmlDoc = CreateXmlDocument(false);
oXmlDoc.loadXML(sXml);


var oLookupIcons = oXmlDoc.selectSingleNode("/fields/lookupicons");
if(!IsNull(oLookupIcons) && oLookupIcons.text.length > 0)
{

var sLookupIcons = oLookupIcons.text + ":";
var iStart = 0, iPos, sURL, iObjType;
while((iPos = sLookupIcons.indexOf(":", iStart)) != -1)
{
iObjType = parseInt(sLookupIcons.substring(iStart, iPos), 10);
iStart = iPos + 1;
iPos = sLookupIcons.indexOf(":", iStart);
_asLookupIcons[iObjType] = sLookupIcons.substring(iStart, iPos);
iStart = iPos + 1;
}
}


return oXmlDoc.parseError.errorCode == 0? oXmlDoc.transformNode(oXslDoc.documentElement) : null;
}



function _getEntityList(sXml)
{

var oXslDoc = CreateXmlDocument(false);

oXslDoc.loadXML("<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'><xsl:output method='xml' omit-xml-declaration='yes'/><xsl:template match='related'><xsl:apply-templates select='result'><xsl:sort select='.' lang='" + XML_LANGUAGE_NAME + "'/></xsl:apply-templates></xsl:template><xsl:template match='result'><option><xsl:apply-templates select='@*'/><xsl:value-of select='.' /></option></xsl:template><xsl:template match='@*'><xsl:attribute name='{name()}'><xsl:value-of select='.' /></xsl:attribute></xsl:template></xsl:stylesheet>");


var oXmlDoc = CreateXmlDocument(false);
oXmlDoc.loadXML(sXml);


return oXmlDoc.parseError.errorCode == 0 ? oXmlDoc.transformNode(oXslDoc.documentElement) : null;
}


function _queryData()
{
var QueryId;
var QueryType;
var Name;
var Description;
var FetchXml;
var LayoutXml;
var EntityName;
var FetchAttributes;
var ReturnType;
}

function _getQuery(sXml)
{

_oQueryXml.loadXML(sXml);

var oQryData = new _queryData();

var node = _oQueryXml.selectSingleNode("//name");
oQryData.Name = (IsNull(node) ? "" : node.text);
node = _oQueryXml.selectSingleNode("//description");
oQryData.Description = (IsNull(node) ? "" : node.text);
node = _oQueryXml.selectSingleNode("//layoutxml");
oQryData.LayoutXml = (IsNull(node) ? "" : node.text);
node = _oQueryXml.selectSingleNode("//fetchxml");
oQryData.FetchXml = (IsNull(node) ? "" : node.text);
node = _oQueryXml.selectSingleNode("//entityname");
oQryData.EntityName = (IsNull(node) ? "" : node.text);
oQryData.FetchAttributes = GetFetchAttributes(oQryData.FetchXml);
node = _oQueryXml.selectSingleNode("//canwrite");
oQryData.CanWrite = (IsNull(node) ? false : node.text == "True");

node = _oQueryXml.selectSingleNode("//returnedtypecode");
oQryData.ReturnType = (IsNull(node) ? "" : node.text );

return oQryData;
}

function _getQueryErr(sHResult, oXmlNode)
{

if(!IsNull(sHResult) && parseInt(sHResult, 16) == parseInt(LOCID_AF_INVALIDENTITY_INQUERY, 16) && !IsNull(oXmlNode))
{

alert(oXmlNode.selectSingleNode("error/description").text);
}
else
{

RemoteCommandDefaultErrorHandler(sHResult, oXmlNode);
}
}




function _getAbstractDataType(oField)
{
switch(oField.getAttribute("datatype"))
{

case "nvarchar":
case "text":
case "string":
return("string");


case "ntext":
case "memo":
return("memo");


case "bit":
case "boolean":
case "state":
case "status":
case "language":
case "picklist":
return("picklist");

case "partylist":
case "primarykey":
case "lookup":
case "customer":


var re = new RegExp("(?:^|,)\\s*8\\s*(?:,|$)", "ig");
if(re.test(oField.lookuptypes))
{

return "lookupwithuser";
}

return("lookup");
case "owner":
return("owner");


case "decimal":
case "integer":
case "int":
case "float":
case "money":
case "number":
return("number");


case "datetime":
case "date":
case "time":
return("date");


default:
return oField.getAttribute("datatype");
}
}


function _containsElement(sEleType, sKey)
{



return !IsNull(_oaCache[sEleType][sKey]) ? _oaCache[sEleType][sKey] : null;
}


function _putElement(sEleType, sKey, vEle)
{
_oaCache[sEleType][sKey] = vEle;
}



function _getElement(sEleType, sKey, vOptParam)
{

var vEle = _containsElement(sEleType, sKey);


if(!IsNull(vEle))
{
return(vEle);
}
else
{

var oaParameters = new Array();


switch(sEleType)
{
case "Entity":

oaParameters["entityName"] = sKey;

vEle = _executeRemoteCommand("GetLinkedEntityList", "AdvancedFind", oaParameters, _getEntityList);
break;

case "Query":

vOptParam["entityName"] = sKey;

vEle = _executeRemoteCommand("GetQueryList", "AdvancedFind", vOptParam, null);
break;

case "Field":

oaParameters["entityName"] = sKey;

vEle = _executeRemoteCommand("GetEntityFieldList", "AdvancedFind", oaParameters, _getFieldList, sKey);
break;

case "SystemQuery":

oaParameters["id"] = sKey;

vEle = _executeRemoteCommand("GetSystemQuery", "AdvancedFind", oaParameters, _getQuery, null, _getQueryErr);
if(!IsNull(vEle))
{
vEle.QueryId = sKey;
vEle.QueryType = SavedQuery;
}
break;

case "UserQuery":

oaParameters["id"] = sKey;

vEle = _executeRemoteCommand("GetUserQuery", "AdvancedFind", oaParameters, _getQuery, null, _getQueryErr);
if(!IsNull(vEle))
{
vEle.QueryId = sKey;
vEle.QueryType = UserQuery;
}
break;

case "Operator":
case "ConditionControlOperator":


vEle = new Select(false, false);
vEle.Render();
break;

case "DefaultAdvFindView":
oaParameters["entityName"] = sKey;
oaParameters["viewIDOnly"] = false;

vEle = _executeRemoteCommand("GetDefaultAdvancedFindView", "AdvancedFind", oaParameters);
if(!IsNull(vEle))
{
var oQryData = _getQuery(vEle);
oQryData.QueryId = GetNodeValue(vEle, "savedqueryid");
oQryData.EntityName = sKey;
oQryData.QueryType = SavedQuery;
oQryData.Name = LOCID_AF_NEWQRYTITLE;

vEle = (IsNull(oQryData.QueryId) || oQryData.QueryId.length == 0) ? null : oQryData;
}
break;

}


if(!IsNull(vEle))
{
_oaCache[sEleType][sKey] = vEle;
}


return vEle;
}
}


function _executeRemoteCommand(sRemoteCommand, sObject, oaParameters, oCallback, vCallbackParam, oErrCallBack)
{

var oRemoteCmd = new RemoteCommand(sObject, sRemoteCommand);


for(var oParam in oaParameters)
{
oRemoteCmd.SetParameter(oParam,oaParameters[oParam]);
}


var bErrHandler = (!IsNull(oErrCallBack) && typeof(oErrCallBack)=="function");
if(bErrHandler)
{
oRemoteCmd.ErrorHandler = oErrCallBack;
}


var oResult = oRemoteCmd.Execute();

if(oResult.Success == ERROR_NONE)
{
var oResultXml = oResult.Xml;
if(!IsNull(oResultXml) && oResultXml.text.length > 0)
{
return (!IsNull(oCallback) && typeof(oCallback)=="function") ? oCallback(oResultXml.text, vCallbackParam) : oResultXml.text;
}
}

return null;
}


function _clearCache(sColl)
{
if(!IsNull(_oaCache[sColl]))
{
_clearColl(_oaCache[sColl]);
}
else
{
for(var ele in _oaCache)
{
_clearColl(ele);
}
}
}


function _clearColl(_aColl)
{
for(var ele in _aColl)
{
delete _aColl[ele];
}
}
}
